package com.devops.admin.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.devops.admin.mapper.DOSProjectVersionReleaseRecordMapper;
import com.devops.admin.mapper.DOSReleaseMapper;
import com.devops.admin.model.*;
import com.devops.admin.po.*;
import com.devops.admin.service.*;
import com.devops.admin.util.Assert;
import com.devops.admin.vo.DOSKubernetesResourceVo;
import com.devops.admin.vo.DOSProjectVersionReleaseRecordVo;
import com.devops.admin.vo.DOSReleaseValuesVo;
import com.devops.admin.vo.DOSReleaseVo;
import com.devops.constant.DevOpsConstant;
import groovy.util.logging.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;

/**
 * @ClassName DOSProjectVersionReleaseRecordServiceImpl
 * @Description TODO
 * @Author heyabo
 * @Date 2022/12/21 11:27
 * @Version 1.0
 **/
@Service
@Slf4j
public class DOSProjectVersionReleaseRecordServiceImpl extends ServiceImpl<DOSProjectVersionReleaseRecordMapper, DOSProjectVersionReleaseRecord>
        implements DOSProjectVersionReleaseRecordService {

    @Autowired
    private DOSReleaseService dosReleaseService;
    @Autowired
    private DOSKubernetesResourceService dosKubernetesResourceService;
    @Autowired
    private DOSHelmChartService dosHelmChartService;
    @Autowired
    private DOSKubernetesYamlRelationService dosKubernetesYamlRelationService;
    @Autowired
    private DOSReleaseMapper dosReleaseMapper;

    @Override
    public void saveRecord(DOSProjectVersionReleaseRecordVo releaseRecordVo) {

        List<DOSProjectVersionReleaseRecord> records = new ArrayList<>();
        // 设置环境
        String envType = getEnvType(releaseRecordVo.getEnvType());
        DOSProjectVersionReleaseRecord record = DOSProjectVersionReleaseRecord.builder()
                .projectId(releaseRecordVo.getProjectId())
                .versionId(releaseRecordVo.getVersionId())
                .recordStatus(releaseRecordVo.getRecordStatus())
                .envType(envType)
                .build();
        String[] split = releaseRecordVo.getEnvType().split(",");
        List<DOSReleasePo> releases;
        List<DOSKubernetesResourcePo> resourcePos;
        if (split.length > 1) {
            // 获取项目的release
            releases = dosReleaseService.getReleasesByProjectId(releaseRecordVo.getProjectId());
            // 获取项目的kubernetesResource
            resourcePos = dosKubernetesResourceService.getList(DOSKubernetesResourceVo.builder()
                    .projectId(releaseRecordVo.getProjectId()).build());
        } else {
            // 获取项目的release
            DOSReleaseVo releaseVo = new DOSReleaseVo();
            releaseVo.setProjectId(releaseRecordVo.getProjectId());
            releaseVo.setEnvType(Integer.valueOf(split[0]));
            releaseVo.setReleaseType(1);
            releases = dosReleaseMapper.selectReleaseListByProjectIdAndEnvType(releaseVo);;
            // 获取项目的kubernetesResource
            resourcePos = dosKubernetesResourceService.getList(DOSKubernetesResourceVo.builder()
                    .projectId(releaseRecordVo.getProjectId())
                    .envTypeId(Integer.valueOf(split[0])).build());
        }

        // 获取release的数据
        if (CollectionUtil.isNotEmpty(releases)) {
            records = getReleaseRecord(record, releases);
        }
        // 获取resource的数据
        if (CollectionUtil.isNotEmpty(resourcePos)) {
            for (DOSKubernetesResourcePo resourcePo : resourcePos) {
                DOSProjectVersionReleaseRecord releaseRecord = new DOSProjectVersionReleaseRecord();
                releaseRecord.setVersionId(record.getVersionId());
                releaseRecord.setProjectId(record.getProjectId());
                releaseRecord.setRecordStatus(record.getRecordStatus());
                releaseRecord.setEnvType(record.getEnvType());
                releaseRecord.setReleaseId(resourcePo.getId());
                releaseRecord.setClusterId(resourcePo.getClusterId());
                releaseRecord.setNamespaceId(resourcePo.getNamespaceId());
                releaseRecord.setReleaseType(DevOpsConstant.ReleaseType.YAML);
                // 查询yaml文件的版本
                List<DOSKubernetesYamlRelation> list = dosKubernetesYamlRelationService.list(Wrappers.<DOSKubernetesYamlRelation>lambdaQuery()
                        .eq(DOSKubernetesYamlRelation::getKubernetesResourceId, resourcePo.getId()).orderByDesc(DOSKubernetesYamlRelation::getYamlRevision));
                if (CollectionUtil.isNotEmpty(list)) {
                    releaseRecord.setReleaseRevision(list.get(0).getYamlRevision());
                }
                releaseRecord.setReleaseValue(resourcePo.getYamlValue());
                records.add(releaseRecord);
            }
        }
        // 如果records为空则表明没有数据被保存
        if (CollectionUtil.isEmpty(records) && releaseRecordVo.getRecordStatus() == 1) {
            return;
        }
        // 批量添加release记录
        this.saveBatch(records);
        // 异步处理releaseValue
        List<DOSProjectVersionReleaseRecord> releaseRecords = records;
        CompletableFuture.runAsync(() -> releaseRecords.forEach(re -> {
            List<DOSProjectVersionReleaseRecord> updateRecords = new ArrayList<>();
            if (re.getReleaseType().intValue() == DevOpsConstant.ReleaseType.HELM) {
                for (DOSReleasePo release : releases) {
                    if (re.getReleaseId().intValue() == release.getId()) {
                        DOSReleaseValuesVo releaseValuesVo = new DOSReleaseValuesVo();
                        releaseValuesVo.setReleaseId(release.getId());
                        releaseValuesVo.setReleaseType(DevOpsConstant.ReleaseType.HELM);
                        releaseValuesVo.setRelease(release.getReleaseName());
                        releaseValuesVo.setNamespace(release.getNamespace());
                        // 获取release的value
                        DOSValuePo values = dosReleaseService.getValues(releaseValuesVo);
                        // 如果value的内容不为空则进行赋值
                        if (StrUtil.isNotEmpty(values.getValue())) {
                            re.setReleaseValue(values.getValue());
                        } else {
                            re.setReleaseValue("null");
                        }
                        updateRecords.add(re);
                    }
                }
            }
            if (CollectionUtil.isNotEmpty(updateRecords)) {
                this.updateBatchById(updateRecords);
            }
        }));
    }

    @Override
    public List<DOSProjectVersionReleaseRecordListPo> getReleaseRecords(DOSProjectVersionReleaseRecordVo releaseRecordVo) {
        Assert.isTrue(releaseRecordVo.getVersionId() != null && releaseRecordVo.getVersionId() > 0, "版本id不能为空");
        Assert.isTrue(releaseRecordVo.getProjectId() != null && releaseRecordVo.getProjectId() > 0, "项目id不能为空");

        List<DOSProjectVersionReleaseRecordListPo> releaseRecordListPoList = new ArrayList<>();
        List<DOSProjectVersionReleaseRecord> releaseRecords = this.list(Wrappers.<DOSProjectVersionReleaseRecord>lambdaQuery()
                .eq(DOSProjectVersionReleaseRecord::getVersionId, releaseRecordVo.getVersionId())
                .eq(DOSProjectVersionReleaseRecord::getProjectId, releaseRecordVo.getProjectId()));

        if (CollectionUtil.isEmpty(releaseRecords)){
            return null;
        }
        String envType = releaseRecords.get(0).getEnvType();

        Map<Integer, List<DOSProjectVersionReleaseRecord>> map = releaseRecords.stream().collect(Collectors.groupingBy(DOSProjectVersionReleaseRecord::getRecordStatus));
        String[] split = envType.split(",");
        List<DOSReleasePo> releases;
        List<DOSKubernetesResourcePo> resourcePos;
        if (split.length > 1){
            // 获取项目的release
            releases = dosReleaseService.getReleasesByProjectId(releaseRecordVo.getProjectId());
            // 获取项目的kubernetesResource
            resourcePos = dosKubernetesResourceService.getList(DOSKubernetesResourceVo.builder()
                    .projectId(releaseRecordVo.getProjectId()).build());
        } else {
            // 获取项目的release
            DOSReleaseVo releaseVo = new DOSReleaseVo();
            releaseVo.setProjectId(releaseRecordVo.getProjectId());
            releaseVo.setEnvType(split[0].equals("uat")?1:2);
            releaseVo.setReleaseType(1);
            releases = dosReleaseService.getReleases(releaseVo);
            // 获取项目的kubernetesResource
            resourcePos = dosKubernetesResourceService.getList(DOSKubernetesResourceVo.builder()
                    .projectId(releaseRecordVo.getProjectId())
                    .envTypeId(split[0].equals("uat")?1:2).build());
        }
        if (CollectionUtil.isNotEmpty(releases) || CollectionUtil.isNotEmpty(resourcePos)){
            Assert.handleData(CollectionUtil.isNotEmpty(map.get(2)),"正在处理数据，请稍后重试...");
            boolean bool = false;
            for (DOSProjectVersionReleaseRecord record : map.get(2)) {
                if (StrUtil.isEmpty(record.getReleaseValue())){
                   bool = true;
                }
            }

            Assert.handleData(!bool,"正在处理数据，请稍后重试...");
        }
        releaseRecords.forEach(record -> {
            if (record.getReleaseValue().equals("null")){
                record.setReleaseValue("");
            }
        });
        // 根据releaseId对结果进行分类
        Map<Integer, List<DOSProjectVersionReleaseRecord>> recordMap = releaseRecords.stream().collect(Collectors.groupingBy(DOSProjectVersionReleaseRecord::getReleaseId));
        for (Map.Entry<Integer, List<DOSProjectVersionReleaseRecord>> listEntry : recordMap.entrySet()) {
            DOSProjectVersionReleaseRecordListPo releaseRecordListPo = new DOSProjectVersionReleaseRecordListPo();
            List<DOSProjectVersionReleaseRecord> records = listEntry.getValue();
            // 查询项目名称，release，集群和命名空间名称 - 从release表里面查询
            DOSReleaseRecordPo recordPo = baseMapper.selectReleaseProjectClusterName(records.get(0));
            if (recordPo == null || StrUtil.isEmpty(recordPo.getProjectName())) {
                // 查询项目名称，release，集群和命名空间名称 - 从yaml文件表里查询
                recordPo = baseMapper.selectResourceProjectClusterName(records.get(0));

            }
            // 为list集合的数据赋值
            for (DOSProjectVersionReleaseRecord record : records) {
                DOSProjectVersionReleaseRecordPo releaseRecordPo = new DOSProjectVersionReleaseRecordPo();
                BeanUtil.copyProperties(record, releaseRecordPo);
                if (recordPo != null) {
                    releaseRecordPo.setProjectName(recordPo.getProjectName());
                    releaseRecordPo.setCluster(recordPo.getClusterName());
                    releaseRecordPo.setNamespace(recordPo.getNamespace());
                    releaseRecordPo.setChartName(recordPo.getChartName());
                    if (StrUtil.isNotEmpty(recordPo.getReleaseName())) {
                        releaseRecordPo.setReleaseName(recordPo.getReleaseName());
                    } else if (StrUtil.isNotEmpty(recordPo.getName())) {
                        releaseRecordPo.setReleaseName(recordPo.getName());
                    }
                }
                if (record.getRecordStatus() == 1) {
                    releaseRecordListPo.setOldReleaseRecords(releaseRecordPo);
                } else if (record.getRecordStatus() == 2) {
                    releaseRecordListPo.setNewReleaseRecords(releaseRecordPo);
                }
            }
            releaseRecordListPoList.add(releaseRecordListPo);
        }
        return releaseRecordListPoList;
    }

    private List<DOSProjectVersionReleaseRecord> getReleaseRecord(DOSProjectVersionReleaseRecord record, List<DOSReleasePo> releases) {
        List<DOSProjectVersionReleaseRecord> records = new ArrayList<>();
        // 获取chartId的集合
        List<Integer> chartIds = releases.stream().map(DOSReleasePo::getChartId).collect(Collectors.toList());
        // 根据chartId的集合获取chart信息的集合
        List<DOSHelmChart> dosHelmCharts = dosHelmChartService.listByIds(chartIds);
        for (DOSReleasePo release : releases) {
            DOSProjectVersionReleaseRecord releaseRecord = new DOSProjectVersionReleaseRecord();
            releaseRecord.setVersionId(record.getVersionId());
            releaseRecord.setProjectId(record.getProjectId());
            releaseRecord.setRecordStatus(record.getRecordStatus());
            releaseRecord.setEnvType(record.getEnvType());
            releaseRecord.setReleaseId(release.getId());
            releaseRecord.setClusterId(release.getClusterId());
            releaseRecord.setNamespaceId(release.getNamespaceId());
            releaseRecord.setReleaseType(DevOpsConstant.ReleaseType.HELM);
            releaseRecord.setReleaseRevision(release.getRevision());
            releaseRecord.setChartId(release.getChartId());
            // 查找chartTag
            for (DOSHelmChart dosHelmChart : dosHelmCharts) {
                if (dosHelmChart.getId().intValue() == release.getChartId()) {
                    releaseRecord.setChartTag(dosHelmChart.getChartTag());
                }
            }

            records.add(releaseRecord);
        }

        return records;
    }

    private String getEnvType(String versionEnvType) {

        if (versionEnvType.contains(DevOpsConstant.EnvType.UAT.toString())) {
            versionEnvType = versionEnvType.replace(DevOpsConstant.EnvType.UAT.toString(), "uat");
        }
        if (versionEnvType.contains(DevOpsConstant.EnvType.PRO.toString())) {
            versionEnvType = versionEnvType.replace(DevOpsConstant.EnvType.PRO.toString(), "pro");
        }

        return versionEnvType;
    }
}
